CvsId "$Id: Ralph.inf,v 1.17 2005/03/14 02:36:27 joelh Exp $"; ! Ideally, this shouldn't let us refer to objects we haven't seen, ! unless they're referenced before they're seen (like the tire, ! bathroom, and case note). ! ! This looks at the ask_in_scope property of each object. This is a ! constant or routine that returns: ! -1: Never in scope ! 0: Don't put in scope (the routine may have already put itself in ! scope), but allow to be put in scope for other reasons. ! (default unless moved or visited) ! 1: Object in scope, subobjects in scope iff object is moved or visited ! 2: Object and subobjects in scope (default if moved or visited) ! 3: Only object in scope; subobjects not automatically in scope [tree_ask_in_scope node is_root scope_rule child_node; if (node provides ask_in_scope) { scope_rule = node.ask_in_scope; if (metaclass(scope_rule) == Routine) scope_rule = node.ask_in_scope(); } else if (node has visited or moved) { scope_rule = 2; } else { scope_rule = 0; } ! Do some preprocessing on scope_rule if ((scope_rule == 0 && ~~is_root) || (scope_rule == 1 && node has moved or visited)) scope_rule = 2; if (scope_rule <= 0) return; PlaceInScope(node); if (scope_rule ~= 2) return; objectloop (child_node in node) tree_ask_in_scope(child_node, false); ]; [all_ask_in_scope obj; switch (scope_stage) { 1: rfalse; 2: objectloop (obj) if (metaclass(obj) == Object) tree_ask_in_scope(obj, true); rtrue; 3: "Flat Feet: Programmer error 69105."; } ]; ! Avoid putting special cases in the Ralph object. That is, if Ralph ! should react in a particular manner when thrown at a particular ! object (say, the aquarium tank), then that should go on the tank, ! not on Ralph. ! ! To facilitate this, we give objects two properties, ralph_act and ! ralph_react. The former, ralph_act, should handle orders ! specifically handed to Ralph (or otherwise undertaken by Ralph). ! For instance, "RALPH, DIG HERE" would call location.ralph_act #Dig. ! This happens for all verbs, and before Ralph does anything on his ! own. Returning false/true lets Ralph do his usual thing or not. ! ! Now, ralph_react handles cases when there has been an action ! involving Ralph and the object. For example, "THROW RALPH AT TANK" ! calls tank.ralph_react #ThrowAt. Ralph may have already undertaken ! some action of his own before it's called, in this example, been ! hurled towards the object. This isn't called for all verbs; check ! ralph.before to see when it's called and add additional calls if ! necessary. Object ralph "Ralph" office with name 'ralph' 'ferret' 'max' 'bjarc', describe [; print "^Ralph, as always, is here"; if (child(self)) { print ", carrying "; WriteListFrom (child(self), ENGLISH_BIT+FULLINV_BIT+TERSE_BIT); } "."; ], description [; print "Ah, your best buddy Ralph. Being a ferret, he's a bit shorter than you are, but much faster. In fact, he never sits still, always jumping around. You and Ralph have been doing this detective gig for years now. In that time, his fast reflexes, keen mind, and suprisingly aerodynamic body have proven crucial to your work time and time again"; if (child(self)) { print ". He is carrying "; WriteListFrom (child(self), ENGLISH_BIT+FULLINV_BIT+TERSE_BIT); } "."; ], ask_in_scope 2, ralph_thinks "~Who, me? Why, Jacques, I didn't know you cared!^ ~I was born a poor black ferret in Waynesport, MO.~^ ~Uh, Ralph~, you interrupt, ~you were born down the street from me in North Dallas.~^ ~Oh, yeah, that's right. So I... er... where was I?~^ ~Waynesport.~^ ~That's right. So I went to PS#105...~^ ~Skip that. What brought you to the bay area?~^ ~Amtrak, mostly, but the train got caught in a snowstorm in Colorado, and I hitchhiked the rest of the way.~^ ~Then what?~^ ~I opened a combination diner/plumbing shop in San Francisco, and ran that until you called me to join you as a PI.~^ ~Thanks, by the way.~^ ~Don't mention it. But I've been by your side ever since.~^ ~That reminds me, Ralph. When I'm on the toilet...~^ ~Yes?~^ ~Ah, nevermind.~", from_sky false, in_bathroom false, found_in [; if (IndirectlyContains(player, ralph)) rfalse; if (IndirectlyContains(location, ralph)) rtrue; if (location ofclass Sky) rfalse; if (self.from_sky) { self.from_sky = false; if (location == mystery_spot) rtrue; ! Ralph's transportation is intentionally nonsensical ! in most cases, which is why Jacques replies like he ! does: to make it clear that the strangeness is part ! of their normal lives. "Ralph is already here.^ ~How'd you get here, Ralph?~^ ~I ", (string)random ("came by airplane", "rode a bicycle", "caught a ride on a blimp", "took a boat", "grabbed a bus", "used a canoe", "flagged down a car", "traveled by stagecoach", "rode a cruise ship", "took the ferry", "came on foot", "flagged down a helicopter", "rode a horse", "hired a limousine", "came on the monorail", "found a motorcycle", "made a raft", "traveled by rail", "took a ship", "came on the subway", "called for a taxi", "came by train", "rode in a truck", "walked"), ".~^ ~Well, that makes sense.~"; } if (self.in_bathroom && location ~= cliff_house) { self.in_bathroom = false; "Ralph joins you. ~All better now!~"; } if (IndirectlyContains(car, player)) ! Ralph is supposedly in the car, so don't print a ! message ! FIXME-8 This doesn't actually put Ralph in the car, ! but that's probably okay. rtrue; "Ralph follows you."; ], time_left 0, time_out [; if (IndirectlyContains(player,ralph)) { if (ralph in player) print "^Ralph squirms out of your grip.^"; else print "^Ralph squirms down from ", (the)parent(ralph), ".^"; move ralph to parent(player); } ], each_turn [; ! Handle THROW RALPH AT HAT. Z. TAKE HAT. if (IndirectlyContains(player,ralph)) ! To understand the number, consider the order in ! which time_out vs each_turn is called. StartTimer(self,0); ], react_before [ oldactor oldaction; PutOn: ! "Put hat on Ralph" if (second == self && noun has clothing) { < Give noun self >; if (parent(noun) == self) { ! The Give succeeded oldactor = actor; actor = self; oldaction = action; action = ##Wear; RunRoutines(self, orders); action = oldaction; actor = oldactor; } rtrue; } ], attack_player [; deadflag = 1; "~Cowabunga!!!!!~ cries Ralph, leapfrogging over your head. As you spin around to face him, Ralph grabs your arm and flips you over his head. You land with a sickening THUD and CRACK, and the various sharp pains in various body parts make you suspect various broken bones.^^ Ralph leaps into the air, and at the apex, does a stunning double-flip into position for his world-famous Skull-Cracker Swan Dive.^^ ~Yee-ha!~ he shouts, and the last thing you see is Ralph's outstretched arms rapidly approaching your face."; ], attack_warned 0, jumpover_done 0, before [; Search: if (~~child(self)) "Ralph is empty-handed."; print "Ralph is carrying "; WriteListFrom (child(self), ENGLISH_BIT+FULLINV_BIT); "."; Take: ! FIXME-3 Look over TakeSub... there's a lot of corner cases ! here. if (ralph in actor) "He's sitting in your arms already."; if (ObjectIsUntouchable(ralph,false,true)) rtrue; move ralph to actor; StartTimer(self,1); self.time_left = 1; ! In case the timer was already running print "~C'mere, buddy!~ you tell Ralph.^^ He leaps into your waiting arms. ~Okay, let's do this thing!~^"; if (onotheld_mode) print "^"; ! The next line is needed for when this is caused by a ! (first taking Ralph) segment. Otherwise, when we ! returned true, the action would be considered ! completed. notheld_mode = onotheld_mode; rtrue; ThrowAt: if (parent(self) ~= actor) "You aren't holding Ralph!"; if (second == self) "Exactly how do you intend to do that?"; if (IndirectlyContains(actor,second)) "You don't have the leverage to get a good throw going in that direction."; ! Note that || apparently doesn't short-circuit. if (second provides can_attack) { if (second.can_attack && RunLife(second, ##Attack)) rtrue; } else { if (RunLife(second, ##Attack)) rtrue; } print "You cock your arm back and make sure you have enough room to get solid follow-through. ~Here we go!~ you cry.^^ ~WEEEE-LAAAAUGH!~ hollers Ralph as you hurl him through the air at ", (the)second, ". Arms outstretched, flying through the air, "; if (second == u_obj) { move ralph to parent(actor); "Ralph does a triple backflip and executes a perfect landing."; } print "Ralph hones in on his target, making tiny in-flight corrections as only a hyperactive overly-violent ferret can.^^"; if (RunRoutines(second,ralph_react)) rtrue; move self to parent(actor); if (second has animate) { print "~With a LEFT! And a RIGHT! And POW! KABLOOIE! WOO-HOO!~^^"; "Ralph seems to really be getting into the action, but you can tell he's just playing with ", (the)second, ". ", (CTheyreorThats)second, " still conscious, after all."; } else if (second has container || second has supporter) { if (children(second) >= ValueOrRun(second, capacity)) { move ralph to location; "There's no room, so Ralph hops back off."; } move ralph to second; print "Ralph nimbly catches onto the edges of ", (the)second, " and perches "; if (second has container) print "within"; if (second has supporter) print "atop"; " ", (itorthem)second, "."; } else if (second == d_obj) { "Ralph hits the ground and does a double cartwheel. ~Ta-da!~"; } else { "Ralph hits ", (the)second, " solidly and flies head over paws grappling with ", (itorthem)second, ", and comes up smiling. ", (The)second, " seems only mildly worse for wear."; } ! Random group 2 actions Close: "Ralph hasn't shut his trap since as long as you've known him."; ! FIXME-5 Handle disrobe, which can happen as both "Disrobe ! Ralph" or as "Doff Ralph", and these have much different ! meanings. Eat: "You can't stomach raw ferret, ever since your time in the SEALs."; Empty: "Ralph will find a bathroom on his own when it becomes necessary."; Enter: "You're just good friends."; Insert: if (~~(ralph in player)) rfalse; if (second has door) "~After you, Jacques!~"; if (second hasnt container) rfalse; if (second == location or d_obj) rfalse; if (RunRoutines(second,ralph_react)) rtrue; print "~No, I don't WANNA go!~ Ralph kicks out his hands and feet, straining against the sides of ", (the)second, ". You force one of his arms back against his body, and his limbs collapse.^"; rfalse; PutOn: if (~~(ralph in player)) rfalse; if (second hasnt supporter) rfalse; if (second == location or d_obj) rfalse; if (RunRoutines(second,ralph_react)) rtrue; Lock,Tie: "Ralph is scared of being locked up, ever since they let him out of the institution. You couldn't inflict such fear on your little buddy, even if ", (the)second, " is sturdy enough."; Open,Unlock: "After all your years together, Ralph's an open book to you already."; Show: print "Ralph proudly strikes a pose.^"; return RunRoutines(second,ralph_react); SwitchOff: ! For the gag reel: "Turn off Ralph" "Some days, you wish you could, but so far you haven't figured out how."; SwitchOn: ! Not for the gag reel: "Turn on Ralph" "He's already as active as ever."; Wear: "Ferret is so last year."; ! Random Group 3 actions Blow: "Just what do you mean by that?"; Burn: "Just the thought of burning ferret hair makes you retch."; Buy: "He's all yours."; Climb: "Ralph's fighting abilities come from his speed, not his strength. He can't support your weight; you're the strong one here."; Cut: << Attack self >>; Dig: "You get your digs in as you can, but nothing comes to mind right now."; Drink: "Ferret, not faucet!"; Fill: "Ralph's already full from his late lunch."; JumpOver: if (self.jumpover_done) "After last time, maybe it's not such a great idea."; if (parent(self) == parent(actor)) { self.jumpover_done = 1; "~Bend down, little buddy, it's time for leapfrog!~^^ ~Whee, I love leapfrog!~ Ralph gets into position. ~Ready, Jacques!~^^ Just as you make your approach, Ralph whips his head up and points upwards. ~Ooh, a shiny thing!~ ^^The resulting experience is painful for you, and you think that maybe leapfrog isn't the way to go."; } "You're not in a good position to play leapfrog right now."; Listen: random_ralph_phrase(); rtrue; LookUnder: "The area is clear of ferret droppings."; Pull: "You grab Ralph's arm. ~Ooh, tug-of-war?~ he says.^^ As you pull on his arm, Ralph bounds around, over, and under you, tangling your arm in a knot. ~I win, I win!~^^You disentangle your arm and try to think of something more practical."; Push: "~Hey, what's the big idea?~ Ralph pushes you back."; PushDir: if (second == u_obj) { if (IndirectlyContains(player, ralph)) "Ralph is as high up as you can get him."; << Take ralph >>; } << Push ralph >>; Rub: "You wipe a bit of grime off of Ralph's fur, but there's plenty still left."; Set: "You wouldn't change your best friend if you could."; Smell: "Whew! Ralph smells like a zoo.^^ ~Hey, Ralph, when did you take a bath?~^^ ~Just last week, but I gave it back.~"; Squeeze: print "~GYAA!~ yelps Ralph. ~"; self.random_exclamation(); ", you're chokin' me here!~ You loosen your grip."; Swing: "~Wheeeeee!~ cries Ralph. ~Vroom, Flight 105 coming in for a landing!~"; Taste: "You eye Ralph over.^^~What is it, Jacques?~^^You lean over for an experimental taste.^^~Blech! Ptooie! Ick!~ cries Ralph. You didn't care for it either."; Touch: "Ralph dodges out of the way. ~Howzabout some personal space here, Jacques?~"; Turn: "I'm not exactly sure how you expect that to work."; Wave: if (parent(self) ~= actor) "You'll need to pick him up first."; << Swing self >>; ], after [; PutOn: "You extend your arm towards ", (the)second, " and Ralph scrambles along it."; ], life [x; Ask: #IfDef NotDef; ! I used to do my own parsing of the consult_words, using ! this code. I had a new problem then: the ReParse code ! never worked right, since pname's NounDomain rewrites ! the input buffer but doesn't retokenize it, and now it's ! too late to retokenize. So I changed it so that the Ask ! and Tell verbs now try to find objects in the normal ! parsing instead. ! ! We use NounDomain from pname.h ! wn = consult_from; ! .ReParse; ! obj = 1; ! while (obj ~= 0) { ! obj = NextWord(); ! print "Starting at ", wn, ":", obj, "^"; ! switch (obj) { ! comma_word,THEN1__WD,'the': ; ! default: obj = 0; ! } ! } ! wn--; ! obj = NounDomain(parent(self), self, NOUN_TOKEN); ! print "Thinking...^"; ! if (obj == REPARSE_CODE) { ! wn = 0; ! jump ReParse; ! } ! if (obj > 1 && self.tell_about(obj)) ! rtrue; ! print "(Looking elsewhere)^"; ! ost = scope_token; ! scope_token = always_in_scope; ! wn = consult_from; ! obj = NounDomain(parent(self), self, NOUN_TOKEN); ! scope_token = ost; ! if (obj == REPARSE_CODE) ! jump ReParse; ! if (obj > 1 && self.tell_about(obj)) ! rtrue; #EndIf; ! As far as I can tell, second will be set to an object, ! a dictionary word, or nothing (in which case use ! consult_words etc). if (metaclass(second) == Object) { ! We have an object that we're asking Ralph about ! specifically. !print "~I have the strange urge to tell you about ", ! (the)second, ".~^"; if (second provides ralph_thinks) { x = PrintOrRun(second, ralph_thinks); if (x) rtrue; } } else switch (second) { ! MIMESIS 'flat', 'feet', 'flibnaub': "~I never play computer games... what a frivolous waste of time.~"; 'call': if (case_note hasnt moved) << Ask ralph case_note >>; 'feeling', 'feelings': "~I'm just spiffy, thanks!~"; 'hooters': ! It's a bar that's all over the USA. Their tagline ! is similar to Ralph's responses about everything in ! Alcatraz. "~Delightfully tacky, yet unrefined.~"; ! Note: if a plural name is used, then that word is ! what's passed instead of the referent. Offhand, the ! only way I know to deal with that is to allow multi ! in this, which is probably not good. Note that ! these don't do checks for scope, but for these, I ! don't particularly care. 'sardines': << Ask ralph sardine >>; 'tickets': << Ask ralph ticket1 >>; } ! Well, we couldn't handle it. Let the library decide. self.random_ralphism(); rtrue; Attack: if (~~self.attack_warned) { self.attack_warned = 1; "That's probably not a good idea... Ralph is a vicious fighter!"; } ! Okay, Ralph's not likely to attack Jacques in my mind, ! but the player defines their relationship. If the ! player sees this kind of a relationship, then who am I ! to argue? print "Okay, if you're sure... You viciously attack Ralph.^^"; self.attack_player(); rtrue; Kiss: "~Look, Jacques, I told you at last year's Christmas party, I really don't feel that way about you.~, says Ralph.^^ ~You never told me that!~^^ ~Well, you weren't around at the time.~"; WakeOther: "Ralph isn't asleep right now. Come to think of it, you can't remember ever seeing Ralph asleep."; ThrowAt: print "Ralph "; if (ralph_holding() ~= nothing) { print "drops ", (the) ralph_holding(), " and "; move ralph_holding() to parent(ralph); } print "plucks ", (the) noun, " out of the air.^"; << Give noun ralph >>; Give: if (noun has worn) { L__M(##Drop, 3, noun); give noun ~worn; } if (noun == ralph) "He's quite self-possessed already."; ! This part is probably unnecessary. x = noun; while (x ~= player) { if (x == nothing) "You aren't holding ", (the)noun, "."; if (x == ralph) "He has a firm grasp on ", (the)noun, " already."; x = parent(x); } ! This part is indeed necessary. (GIVE RALPH TO RALPH, or, ! PUT RALPH IN HAT.GIVE HAT TO RALPH) x = ralph; while (x ~= nothing) { if (x == noun) "Exactly how did you intend for that to work?"; x = parent(x); } if (ralph_holding() ~= nothing) { "Ralph seems to be having fun playing with ", (the) ralph_holding(), ", and doesn't notice your offer."; } move noun to ralph; print "He graciously accepts ", (the)noun, ". ~"; self.random_exclamation(); ", thanks!~"; Show: << Ask ralph noun >>; Tell: print_ret (string)random( "~What makes you think I care?~", "~Who asked your opinion?~", "~I don't see what the big deal is.~"); Order: if (action == ##NotUnderstood) { self.random_ralphism(); rtrue; } print_ret (string)random( "~You show me how.~", "~I don't wanna!~", "~Let's not and say we did.~", "~Never!~", "~I promised my great grandpappy that I wouldn't.~", "~Not without a hamster.~", "~Never before breakfast.~", "~My religion forbids me from doing that on a Wednesday.~", "~Not after that time in '86. I still get shivers.~", "~And what if I don't feel like it?~"); Answer: #IfDef Debug; if (consult_words == 2) { wn = consult_from; if (NextWord() == 'solve') { print "Ralph goes into debugging mode to quickly solve obstacles.^"; switch (NextWord()) { 'tire': tire.tied = false; tire.balanced = true; move tire to player; "~You got it!~ He fetches and balances the tire."; 'car': tire.tied = false; tire.balanced = true; car.working = true; give tire moved; remove tire; "~You got it!~ He fixes the car."; 'note': move case_note to player; "~You got it!~ He gives you the case note."; 'clues': move photograph to player; if (calling_card.place == nothing) calling_card.set_place(); move calling_card to player; move map_scrap to player; "~You got it!~ He gives you the clues."; default: "~Do WHAT?~"; } rtrue; } } #EndIf; self.random_ralphism(); rtrue; ], orders [nh onh; if (metaclass(noun) == Object && RunRoutines(noun,ralph_act)) rtrue; ! In theory, it seems like many of these should be ! handlable with just << wear noun >> or the like. But ! many library routines use "player" where they probably ! should use "actor" (unless I'm missing the point). Attack: ! If you change this, check ENTER. if (noun == player) { self.attack_player(); rtrue; } actor = player; if (~~(ralph in actor)) { ! I don't really understand onotheld_mode and ! notheld_mode, so this is just a guess that seems to ! work. nh = notheld_mode; onh = onotheld_mode; onotheld_mode = 1; < Take self >; notheld_mode = nh; onotheld_mode = onh; } if (ralph in actor) << ThrowAt self noun >>; Examine: actor = player; << Ask self noun >>; Dig,DigDown: if (noun == d_obj or nothing) { noun = location; ! The location may not have gotten a chance to ralph_act if (RunRoutines(noun,ralph_act)) rtrue; } "~What, here? I might damage my finely sharpened claws.~"; Climb: if (noun == player) { StartTimer(self,1); self.time_left = 1; ! In case the timer was already running if (parent(self) == player) "Ralph adjusts his position to rest on your shoulders."; move ralph to player; "~You got it, big guy!~ Ralph nimbly climbs onto your shoulders."; } "~I ain't climbing ", (thatorthose)noun, " without a net.~"; Wear: if (parent(noun) ~= actor) "~I'm not holding ", (thatorthose)noun, "!~"; if (noun hasnt clothing) "~", (Thatorthose)noun, " ", (isorare)noun, " hardly my size!~"; if (noun has worn) "~I'm already wearing ", (itorthem)noun,"!~"; give noun worn; if (AfterRoutines() == 1) rtrue; if (keep_silent == 1) rtrue; print_ret (The)actor, " puts on ", (the)noun, "."; Disrobe: if (parent(noun) ~= actor) "~I don't even have ", (thatorthose)noun, "!~"; if (noun hasnt worn) "~I'm not wearing ", (thatorthose)noun, "!~"; give noun ~worn; if (AfterRoutines() == 1) rtrue; if (keep_silent == 1) rtrue; print_ret (The)actor, " takes off ", (the)noun, "."; Take: if (noun == player) "~You're too heavy for me to lift.~"; ! FIXME-7 Cheap cop-out to handle how hideous it is to ! port TakeSub to a NPC. Don't forget that some things, ! such as MOVED (which I use frequently) aren't even ! handled by TakeSub. "~I don't feel like reaching. Give it here yourself.~"; Give: if (parent(noun) ~= actor) "Ralph doesn't have ", (the) noun, "."; if (second == actor) print_ret (the) actor, " juggles ", (the) noun, " for a while, but doesn't achieve much."; if (second ~= player && RunLife(second, ##Give) ~= 0) rtrue; print "Ralph "; if (noun has worn) { give noun ~worn; print "takes off ", (the)noun, " and "; } move noun to second; "gives ", (the)noun, " to ", (thatorthose)second, "."; Drop: ! FIXME-6 The sequence RALPH, DROP (return) RALPH, HAT ! screws up. if (noun == actor) "Ralph is very dexterous, but not by that much."; if (noun in parent(actor)) "Ralph looks pointedly at ", (the)noun, ", already out of his possession."; if (~~IndirectlyContains(actor, noun)) ! Note: This probably won't ever happen, since the ! library prints "You haven't got that." by now. "~I haven't got ", (itorthem)noun, ".~"; if (noun notin actor) { nh = parent(noun); << Drop nh >>; } if (noun has worn) { L__M(##Drop, 3, noun); ; if (noun has worn && noun in actor) rtrue; } ! Here to allow AfterRoutines to print. print "With a disappointed grunt, Ralph drops it.^"; move noun to parent(actor); AfterRoutines(); rtrue; Enter: ! If you change this, change Attack too. actor = player; if (noun == player) << Take ralph >>; actor = player; if (~~(ralph in actor)) { ! I don't really understand onotheld_mode and ! notheld_mode, so this is just a guess that seems to ! work. nh = notheld_mode; onh = onotheld_mode; onotheld_mode = 1; < Take self >; notheld_mode = nh; onotheld_mode = onh; } if (ralph in actor) << ThrowAt self noun >>; ! Random orders Go: "~Age before beauty!~^~And pearls before swine.~"; Swim: if (aquarium_tank in location) << Enter aquarium_tank >>; ], random_ralphism [; if (random(5) == 1) { print "~"; self.random_exclamation(); "!~"; } print_ret (string)random( "~Huh? What? I forgot what we were talking about!~", "~So what's your point?~", "~Are you thinking what I'm thinking?~^ ~I think so, but that show isn't on anymore.~", "~And why don't you ever ask about my feelings?~", "~Maybe there's a good reason things are the way they are.~", "~I don't believe in anything that doesn't believe in me.~", "~I make it a point to never discuss such things on a Wednesday.~", "~Your voice sounds strange; have you been eating enough bacon?~", "~Maybe we should ignore absolutely everything.~", "~That's a silly thing to talk about.~^ ~Made sense to me.~^ ~It's a reasonable thing for YOU to talk about, but I think it's silly.~", "Ralph ignores you and yawns.", "~Mumble mumble frotz.~", "~Must we really discuss such things?~" ); ], random_exclamation [; ! Note: these don't come with punctuation or quote marks! print (string)random ( "Heavens to Murgatroid", ! Snagglepuss "Great jangling jelly-babies", ! Insp. Fowler (Thin Blue Line) "Holy exclamations, Jacques", ! Robin (from Batman) "Gee whiz golly jeepers", ! Dennis the Menace "Great googly moogly", ! Liberty Meadows & others "Leapin' lizards", ! Annie "Cowabunga", ! Simpsons ); ], has animate male proper transparent; [ ralph_holding obj; objectloop (obj in ralph) if (obj hasnt worn) return obj; return nothing; ]; [ random_ralph_phrase; "~I don't know what to say here,~ says Ralph."; ]; ! Local variables: ! inform-project-file:"Flibnaub.inf" ! End: